import { store } from '@/store/store';
import { Toast } from 'antd-mobile';
import axios from 'axios';
import { customHistory } from './history';
import { clearToken, setToken } from './token';

// 导出一个自定义 axios 实例
export const http = axios.create({
  // baseURL: 'http://toutiao.itheima.net/v1_0',
  baseURL: 'http://geek.itheima.net/v1_0',
  timeout: 5000,
});

// 1 请求拦截器
http.interceptors.request.use((config) => {
  // console.log('config', config);
  // config 处理流程中配置对象
  // 根据url添加token
  const token = store.getState().login.token;

  // 除登录外的接口，都传token
  if (!config.url?.startsWith('/authorizations')) {
    // 添加token
    config.headers!.Authorization = `Bearer ${token}`;
  }

  // 别忘了把config交给后面流程处理
  return config;
});

// 2 响应拦截器
http.interceptors.response.use(undefined, async (error) => {
  // console.log('error', error);
  // 处理超时
  if (!error.response) {
    // 这是开发者对异常统一处理
    console.log('超时错误发生了');
    Toast.show({ content: '网络繁忙，请稍后再试', duration: 500 });
    return Promise.reject(error);
  }

  // token 过期
  if (error.response.status === 401) {
    console.log('token过期');
    try {
      // 1 换取token
      // 1.1 拿到 refresh_token
      const refresh_token = store.getState().login.refresh_token;
      if (!refresh_token) {
        // refresh_token 不存在，直接抛出异常交给catch统一处理
        throw new Error('refresh_token不存在');
      }

      // 1.2 发起新的请求获取token
      const res = await axios.put(
        'http://toutiao.itheima.net/v1_0/authorizations',
        null,
        {
          headers: {
            Authorization: `Bearer ${refresh_token}`,
          },
        }
      );
      // 1.3 保存新的token
      const newToken = {
        token: res.data.data.token,
        refresh_token: refresh_token,
      };
      // 本地一套
      setToken(newToken);
      // redux一套
      store.dispatch({
        type: 'login/token',
        payload: newToken,
      });

      // 1.4 重新发送之前的请求
      return http(error.config);
    } catch (error) {
      // 2 换取失败
      // 2.1 清理本地token
      clearToken();
      // 2.2 清理redux token。只能dispatch 对象形式的 action
      store.dispatch({
        type: 'login/token',
        payload: { token: '', refresh_token: '' },
      });
      // 2.3 提示用户
      Toast.show({
        content: 'Token过期，请重新登录',
        duration: 1000,
        afterClose: () => {
          customHistory.push('/login', {
            from: customHistory.location.pathname,
          });
        },
      });
      // 2.4 控制权交给axios
      return Promise.reject(error);
    }
  }

  // 把错误处理权交还给axios
  return Promise.reject(error);
});
